﻿/*
Copyright © 2010 François Karman

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

See <license.txt> for the complete license of the software.
*/

using System.Collections;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;

namespace Faz.Dependencies.Controls
{
    /// <summary>
    /// Defines a view that can be used with <see cref="ListView"/> to display
    /// the elements as part of a graph.
    /// </summary>
    public class LinkView : ViewBase
    {
        /// <summary>
        /// Identifies the <see cref="LinkView.LevelPropertyName"/> property.
        /// </summary>
        public static readonly DependencyProperty LevelPropertyNameProperty =
            DependencyProperty.Register("LevelPropertyName", typeof(string), typeof(LinkView), new PropertyMetadata("Level"));

        /// <summary>
        /// Identifies the <see cref="LinkView.DependenciesPropertyName"/> property.
        /// </summary>
        public static readonly DependencyProperty DependenciesPropertyNameProperty =
            DependencyProperty.Register("DependenciesPropertyName", typeof(string), typeof(LinkView), new UIPropertyMetadata("Dependencies"));

        public static readonly DependencyProperty LineStartTemplateProperty =
            DependencyProperty.Register("LineStartTemplate", typeof(ControlTemplate), typeof(LinkView));

        public static readonly DependencyProperty LineEndTemplateProperty =
            DependencyProperty.Register("LineEndTemplate", typeof(ControlTemplate), typeof(LinkView));

        /// <summary>
        /// Initializes a new instance of the LinkView class.
        /// </summary>
        public LinkView()
        {
        }

        /// <summary>
        /// Gets or sets the name of the property containing the level of an object.
        /// </summary>
        /// <value>
        /// The default value of this property is <c>Level</c>.
        /// </value>
        public string LevelPropertyName
        {
            get { return (string)this.GetValue(LevelPropertyNameProperty); }
            set { this.SetValue(LevelPropertyNameProperty, value); }
        }

        /// <summary>
        /// Gets or sets the name of the property containing the dependencies of an object.
        /// </summary>
        /// <value>
        /// The default value of this property is <c>Dependencies</c>.
        /// </value>
        public string DependenciesPropertyName
        {
            get { return (string)GetValue(DependenciesPropertyNameProperty); }
            set { SetValue(DependenciesPropertyNameProperty, value); }
        }

        public ControlTemplate LineStartTemplate
        {
            get { return (ControlTemplate)GetValue(LineStartTemplateProperty); }
            set { SetValue(LineStartTemplateProperty, value); }
        }

        public ControlTemplate LineEndTemplate
        {
            get { return (ControlTemplate)GetValue(LineEndTemplateProperty); }
            set { SetValue(LineEndTemplateProperty, value); }
        }

        /// <summary>
        /// Gets the key associated with the style of the <see cref="ListView"/>
        /// for the view mode.
        /// </summary>
        protected override object DefaultStyleKey
        {
            get { return new ComponentResourceKey(this.GetType(), "DefaultStyleKey"); }
        }

        /// <summary>
        /// Gets the key associated with the style to use for the items in the view mode.
        /// </summary>
        protected override object ItemContainerDefaultStyleKey
        {
            get { return new ComponentResourceKey(this.GetType(), "ItemContainerDefaultStyleKey"); }
        }

        /// <summary>
        /// Retrieves the level of a specific element.
        /// </summary>
        /// <param name="content">The element to explore.</param>
        /// <returns>The level of the element or -1.</returns>
        public int RetrieveLevel(object content)
        {
            if (content == null)
            {
                return -1;
            }

            PropertyInfo property = content.GetType().GetProperty(this.LevelPropertyName, typeof(int));
            if (property == null)
            {
                return -1;
            }
            else
            {
                return (int)property.GetValue(content, null);
            }
        }

        /// <summary>
        /// Retrieves all the dependencies associated to a specific element.
        /// </summary>
        /// <param name="content">The element to explore.</param>
        /// <returns>The dependencies of the element or <c>null</c>.</returns>
        public IEnumerable ExtractDependencies(object content)
        {
            if (content == null)
            {
                return null;
            }

            PropertyInfo property = content.GetType().GetProperty(this.DependenciesPropertyName);
            return (IEnumerable)property.GetValue(content, null);
        }
    }
}
